package visitor

import (
	"fmt"
	"math"
)

// Visitor 因为不同的图形计算面积和周长的方式不同，所以需要不同的访问者
type Visitor interface {
	VisitCircle(circle *Circle)
	VisitRectangle(rectangle *Rectangle)
}

type Shape interface {
	Accept(visitor Visitor)
}

type Circle struct {
	radius float64
}

func (c *Circle) Accept(visitor Visitor) {
	visitor.VisitCircle(c)
}

type Rectangle struct {
	width  float64
	height float64
}

func (c *Rectangle) Accept(visitor Visitor) {
	visitor.VisitRectangle(c)
}

type AreaVisitor struct {
}

func (c *AreaVisitor) VisitCircle(circle *Circle) {
	fmt.Println("Circle area: ", math.Pi*circle.radius*circle.radius)
}

func (c *AreaVisitor) VisitRectangle(rectangle *Rectangle) {
	fmt.Println("Rectangle area: ", rectangle.width*rectangle.height)
}

type PerimeterVisitor struct {}

func (c *PerimeterVisitor) VisitCircle(circle *Circle) {
	fmt.Println("Circle perimeter: ", 2*math.Pi*circle.radius)
}

func (c *PerimeterVisitor) VisitRectangle(rectangle *Rectangle) {
	fmt.Println("Rectangle perimeter: ", 2*(rectangle.width+rectangle.height))
}
